import '../../css/drag.css';
import __DB__               from '../db/index.js';
import __canvas__           from '../canvas/index.js';
import __tool__             from '../tool/index.js';
import __formate__          from '../formate/index.js';
import __customEvent__      from '../customEvent/index.js';
import __line__             from '../line/index.js';

class dragClass{
    constructor(){
        // 自由节点拖拽距离根节点的偏移量
        this.rootOffsetX = 0;
        this.rootOffsetY = 0;

        this.dragId         = null; //拖拽节点的id
        this.dragLabel      = '';   //拖拽节点的label
        this.dragNodeType   = '';   //拖拽节点的label
        this.dragOtherIds   = [];   //拖拽节点的otherIds
        this.dragPid        = null; //拖拽目标节点id
        this.enterType      = null; //拖拽的类型(in,up,down,free)
        this.enterTypeRoot  = null; //目标节点是否是根节点
        this.dragEl         = null; //拖拽元素
        this.dragData       = null; //拖拽节点的额外信息
        this.dragNewNode    = false;//拖拽出新节点
    }

    // 初始化
    use(){
        this.enterIn();     // 进入节点
        this.enterUp();     // 进入节点上方
        this.enterDown();   // 进入节点下方
    }

    // 进入节点
    enterIn(){
        const nodesIn = document.querySelectorAll('.xmd-node-in');
        for(let el of nodesIn){
            el.onmouseover = (e)=>{
                e.stopPropagation();
                let elDraw = document.getElementById('drawDiv');
                
                if(!elDraw)return;
                let id = el.parentNode.getAttribute('id');

                this.dragPid = id;
                let isNext = this.checkDrag();
                if(!isNext){
                    this.dragPid = null;
                    return;
                }
                
                el.classList.add('active');

                let x = parseFloat(el.parentNode.style.left),
                    y = parseFloat(el.parentNode.style.top),
                    w = parseFloat(el.parentNode.getBoundingClientRect().width)/__canvas__.scale,
                    h = parseFloat(el.parentNode.getBoundingClientRect().height)/__canvas__.scale;
                
                this.dragPid = id;
                this.enterType = "in";
                if(__DB__.get(id).root){
                    let theN = __DB__.get(id);
                    let w_root = theN.node.init.size.w;
                    el.onmousemove = (evv)=>{
                        let ox = evv.offsetX;
                        if(ox<=0 || ox >=w)return;
                        
                        this.vBox({show:false});    
                        __line__.del({id:"vline"});
                        if(ox > w_root/2){
                            this.enterType = "in";
                            this.enterTypeRoot = "right";
                            fn_right.call(this,{x,y,w,h});
                        }
                        else{
                            this.enterTypeRoot = "left";
                            fn_left.call(this,{x,y,w,h});
                        }
                    }
                    el.onmouseup = ()=>{
                        el.onmousemove = null;
                        el.onmouseup = null;
                    }
                    return;
                }
                
                let left = __DB__.get(id).flip;
                if(left){
                    fn_left.call(this,{x,y,w,h});
                }
                else{
                    fn_right.call(this,{x,y,w,h});
                }
                
            };

            el.onmouseout = (e)=>{
                let elDraw = document.getElementById('drawDiv');
                el.classList.remove('active');
                if(!elDraw)return;
                this.dragPid = null;
                this.enterType = 'free';
                this.clear();
            };
        }

        function fn_left(res) {
            let x = res.x,
                y = res.y,
                w = res.w,
                h = res.h;
            
            let x1 = x,
                y1 = y + h/2,
                x2 = x - 20,
                y2 = y + h/2
            
            __line__.add({
                id:"vline",
                x1,y1,x2,y2,
            });
                
            this.vBox({
                x:x - 90,
                y:y + (h - 20)/2,
                show:true
            });
        }

        function fn_right(res) {
            let x = res.x,
                y = res.y,
                w = res.w,
                h = res.h;
            let x1 = x + w,
                y1 = y + h/2,
                x2 = x + w + 20,
                y2 = y + h/2;
            
            // __line__.add({
            //     id:"vline",
            //     x1,y1,x2,y2,
            // });
                
            this.vBox({
                x:x + w + 20,
                y:y + (h - 20)/2,
                show:true
            });
        }
    }

    // 进入节点上方
    enterUp(){
        const nodesUp = document.querySelectorAll('.xmd-node-up');
        for(let el of nodesUp){
            el.addEventListener('mouseover',(e)=>{
                e.stopPropagation();
                let elDraw = document.getElementById('drawDiv');
                if(!elDraw)return;
                let id = el.parentNode.getAttribute('id');
                if(__DB__.get(id).nodeType === "free")return;
                if(__DB__.get(id).root)return;
                if(this.dragId === id)return;

                this.dragPid = id;
                let isNext = this.checkDrag();
                if(!isNext){
                    this.dragPid = null;
                    return;
                }

                this.enterType = 'up';

                let dragPid = elDraw.getAttribute('pid');
                if(dragPid === id)return;
                el.classList.add('active');

                for(let item of el.parentNode.childNodes){
                    if(item.classList[0]==="xmd-node-in"){
                        item.classList.add('active');
                        break;
                    }
                }

                let x = parseFloat(el.parentNode.style.left),
                    y = parseFloat(el.parentNode.style.top),
                    w = parseFloat(el.parentNode.getBoundingClientRect().width),
                    h = parseFloat(el.parentNode.getBoundingClientRect().height);
                
                let left = __DB__.get(id).flip;
                if(left){
                    fn_left.call(this,{x,y,w,h});
                }
                else{
                    fn_right.call(this,{x,y,w,h});
                }

            });

            el.addEventListener('mouseout',(e)=>{
                let elDraw = document.getElementById('drawDiv');
                if(!elDraw)return;
                this.dragPid = null;
                this.enterType = 'free';
                this.clear();
            });
        }

        function fn_left(res) {
            let x = res.x,
                y = res.y,
                w = res.w/__canvas__.scale,
                h = res.h/__canvas__.scale;
            
            let x1 = x,
                y1 = y - 5,
                x2 = x - 20,
                y2 = y - 10
            
            // __line__.add({
            //     id:"vline",
            //     x1,y1,x2,y2,
            // });
                
            // this.vBox({
            //     x:x - 90,
            //     y:y - 20,
            //     show:true
            // });
        }

        function fn_right(res) {
            let x = res.x,
                y = res.y,
                w = res.w/__canvas__.scale,
                h = res.h/__canvas__.scale;
            
            let x1 = x + w,
                y1 = y - 5,
                x2 = x + w + 20,
                y2 = y - 10
            
            // __line__.add({
            //     id:"vline",
            //     x1,y1,x2,y2,
            // });
                
            // this.vBox({
            //     x:x + w + 20,
            //     y:y - 20,
            //     show:true
            // });
        }
    }

    // 进入节点下方
    enterDown(){
        const nodesDown = document.querySelectorAll('.xmd-node-down');
        for(let el of nodesDown){
            el.addEventListener('mouseover',(e)=>{
                e.stopPropagation();
                let elDraw = document.getElementById('drawDiv');
                if(!elDraw)return;
                let id = el.parentNode.getAttribute('id');
                if(__DB__.get(id).nodeType === "free")return;
                if(__DB__.get(id).root)return;
                if(this.dragId === id)return;

                this.dragPid = id;
                let isNext = this.checkDrag();
                if(!isNext){
                    this.dragPid = null;
                    return;
                }

                el.classList.add('active');
                
                this.dragPid = id;
                this.enterType = "down";
                for(let item of el.parentNode.childNodes){
                    if(item.classList[0]==="xmd-node-in"){
                        item.classList.add('active');
                        break;
                    }
                }

                let x = parseFloat(el.parentNode.style.left),
                    y = parseFloat(el.parentNode.style.top),
                    w = parseFloat(el.parentNode.getBoundingClientRect().width),
                    h = parseFloat(el.parentNode.getBoundingClientRect().height);

                let left = __DB__.get(id).flip;
                if(left){
                    fn_left.call(this,{x,y,w,h});
                }
                else{
                    fn_right.call(this,{x,y,w,h});
                }
            });

            el.addEventListener('mouseout',(e)=>{
                let elDraw = document.getElementById('drawDiv');
                if(!elDraw)return;
                this.dragPid = null;
                this.enterType = 'free';
                this.clear();
            });
        }

        function fn_left(res) {
            let x = res.x,
                y = res.y,
                w = res.w/__canvas__.scale,
                h = res.h/__canvas__.scale;
            
            let x1 = x,
                y1 = y + h + 5,
                x2 = x - 20,
                y2 = y + h +10 
            
            // __line__.add({
            //     id:"vline",
            //     x1,y1,x2,y2,
            // });
                
            // this.vBox({
            //     x:x - 90,
            //     y:y + h,
            //     show:true
            // });
        }

        function fn_right(res) {
            let x = res.x,
                y = res.y,
                w = res.w/__canvas__.scale,
                h = res.h/__canvas__.scale;

            let x1 = x + w,
                y1 = y + h + 5,
                x2 = x + w + 20,
                y2 = y + h + 10
            
            // __line__.add({
            //     id:"vline",
            //     x1,y1,x2,y2,
            // });
                
            // this.vBox({
            //     x:x + w + 20,
            //     y:y + h,
            //     show:true
            // });
        }
    }

    // 拖拽时的临时模块-预显示
    /*
        vBox();
        show:开启/关闭
        x,
        y,
    */
    vBox(res){
        if(!res.show){
            let elBox = document.getElementById('vbox');
            if(elBox)__canvas__.canvas.removeChild(elBox);
            return;
        }

        let x = res.x,
            y = res.y;
        let elBox = document.createElement('div');
        elBox.setAttribute('id','vbox');
        elBox.setAttribute('class','xmd-vbox');
        elBox.style.left = x + 'px';
        elBox.style.top  = y + 'px';
        __canvas__.canvas.appendChild(elBox);
    }

    // 外部拖拽模块
    outsideModule(res){
        let id          = res.id,
            label       = res.label,
            e           = res.e,
            nodeType    = res.nodeType;

        this.dragNewNode = true;//拖拽出新节点

        this.dragData = res;

        this.start({
            e,
            el:e.target,
            parentNode:null,
            id,
            label,
            nodeType
        });
    }

    // 开始拖拽
    /*
        __drag__.start();
        e           : DOM
        el          : DOM.target
        parentNode  : DOM.parent
    */
    start(res){
        let e           = res.e;
        let id          = res.id;
        let otherIds    = res.otherIds||[];
        let theData     = __DB__.get(id);
        let label       = theData?theData.label:res.label;
        let nodeType    = res.nodeType;

        if(__DB__.get(id)&&__DB__.get(id).root)return;// 过滤根节点

        this.enterType = 'free';

        // 拖拽的临时模块HTML
        this.temporaryModule({
            type:"create",
            id,
            label
        });

        let ox = e.offsetX*__canvas__.scale;
        let oy = e.offsetY*__canvas__.scale;

        // 标记变量-用于单击使用
        let onceOffMove = 0;
        let onceOffUp   = true;
        document.onmousemove = (ev)=>{
            let x = ev.clientX - ox,
                y = ev.clientY - oy;
            if(onceOffMove < 3){
                onceOffMove++;
                return;
            }

            onceOffUp           = false;
            this.dragId         = id;
            this.dragLabel      = label;
            this.dragNodeType   = nodeType;
            this.dragOtherIds   = otherIds;

            overMoudle();

            this.updatePoi({x,y});// 设置拖拽对象位置 
        }

        document.onmouseup = (ev)=>{
            document.onmousemove                = null;
            document.onmouseup                  = null;
            __canvas__.main.onmouseout          = null;
            __canvas__.main.onmouseover         = null;

            let x = ev.offsetX - e.offsetX;
            let y = ev.offsetY - e.offsetY;

            let rootData = __DB__.get('root');
            let root_x = rootData.node.init.poi.x;
            let root_y = rootData.node.init.poi.y;

            this.rootOffsetX = root_x - x;
            this.rootOffsetY = root_y - y;

            this.temporaryModule({type:"remove"});// 删除拖拽对象
            outMoudle();
            this.clear(); // 清理拖拽

            if(onceOffUp)return;
            onceOffUp = true;
            
            this.releaseReset();// 拖拽结束重置节点排版
        }

        function overMoudle(){
            const nodesIn = document.querySelectorAll('.xmd-node-in');
            for(let el of nodesIn){
                el.style.display = "block";
            }

            const nodesUp = document.querySelectorAll('.xmd-node-up');
            for(let el of nodesUp){
                el.style.display = "block";
            }

            const nodesDown = document.querySelectorAll('.xmd-node-down');
            for(let el of nodesDown){
                el.style.display = "block";
            }
        }
        function outMoudle(){
            const nodesIn = document.querySelectorAll('.xmd-node-in');
            for(let el of nodesIn){
                el.style.display = "none";
            }

            const nodesUp = document.querySelectorAll('.xmd-node-up');
            for(let el of nodesUp){
                el.style.display = "none";
            }

            const nodesDown = document.querySelectorAll('.xmd-node-down');
            for(let el of nodesDown){
                el.style.display = "none";
            }
        }
    }

    // 拖拽的临时模块HTML
    /*
        temporaryModule();
        type        : 方法类型
        id          : 节点ID
        label       : 节点标题
    */
    temporaryModule(res){
        let type    = res.type,
            id      = res.id,
            label   = res.label;

        if(type === 'create'){
            this.dragEl = document.createElement('div');
            this.dragEl.setAttribute('id','drawDiv');
            this.dragEl.setAttribute('class','xmd-drawDiv');
            this.dragEl.setAttribute('nodeId',id);
            this.dragEl.style.opacity = 0;
            this.dragEl.innerHTML = label;

            let w = document.getElementById(id)?document.getElementById(id).getBoundingClientRect().width:100;
            let h = document.getElementById(id)?document.getElementById(id).getBoundingClientRect().height:50;
            this.dragEl.style.width  = w + "px";
            this.dragEl.style.height = h + "px";
            this.dragEl.style.lineHeight = h + "px";
            this.dragEl.style.zIndex = -1;
            document.body.appendChild(this.dragEl);
            return;
        }

        if(type === "remove"){
            document.body.removeChild(this.dragEl);
            this.dragEl = null;
            return;
        }
    }

    // 校验是否可拖到的节点
    checkDrag(){
        let dragId      = this.dragId,
            dragPid      = this.dragPid;
        
        this.enterType = "own";
        let data_dragId     = __DB__.get(dragId)?__tool__.deepCopy(__DB__.get(dragId)):null;

        if(this.dragNewNode)return true;

        if(dragId === dragPid){
            return false;
        }

        if(data_dragId.nodeType==="free"){
            if(!__DB__.nodesManyIds[dragId]){
                return false;
            }

            if(__DB__.nodesManyIds[dragId].includes(dragPid)){
                return false;
            }
            return true;
        }

        if(!__DB__.nodesManyIds[dragId]){
            return false;
        }

        if(__DB__.nodesManyIds[dragId].includes(dragPid)){
            return false;
        }

        return true;
    }

    // 设置拖拽对象位置
    /*
        updatePoi();
        x:横坐标
        y:纵坐标
    */
    updatePoi(res){
        let x = res.x,
            y = res.y;
        this.dragEl.style.left      = x + "px";
        this.dragEl.style.top       = y + "px";
        this.dragEl.style.opacity   = 1;
        this.dragEl.style.zIndex    = 1;
    }

    // 拖拽结束重置节点排版
    releaseReset(){
        let dragId              = this.dragId,
            dragPid             = this.dragPid,
            dragLabel           = this.dragLabel,
            dragNodeType        = this.dragNodeType,
            dragOtherIds        = this.dragOtherIds,
            enterType           = this.enterType;
            
        if(enterType === "own")return;
        
        let dragIdData  = dragId?__tool__.deepCopy(__DB__.get(dragId)):{};
        let dragPidData = dragPid?__tool__.deepCopy(__DB__.get(dragPid)):null;

        if(this.dragNewNode){
            let newNodeData = this.dragData;
            dragId = newNodeData.id;
            dragIdData = __formate__.nodeDataModel({
                id          : newNodeData.id,
                label       : newNodeData.label,
                nodeType    : newNodeData.nodeType,
                type        : 'tree',
            })

            // 绑定自定义事件
            __customEvent__.set({
                type:"nodeDragAdd",
                data:{
                    id:dragId,
                    label:newNodeData.label,
                    data:newNodeData.data
                }
            });
        }

        if(enterType === "in"){
            fn_in.call(this);
        }
        if(enterType === "up"){
            fn_up.call(this);
        }
        if(enterType === "down"){
            fn_down.call(this);
        }
        if(enterType === "free"){
            fn_free.call(this);
        }
        
        // 绑定自定义事件
        __customEvent__.set({
            type:"nodeDrag",
            data:{id:dragId,label:dragIdData.label}
        });
        __DB__.reset();// 重新渲染
        this.dragNewNode = false;//拖拽出新节点

        function fn_in(){
            if(dragPid !== dragIdData.pid){
                fn.call(this,{
                    id:dragId,
                    pid:dragPid,
                    label:dragLabel,
                    nodeType:dragNodeType,
                    pidData:dragPidData
                });

                if(dragOtherIds.length > 0){
                    for(let el of dragOtherIds){
                        fn.call(this,{
                            id:el,
                            pid:dragPid,
                            label:dragLabel,
                            nodeType:dragNodeType,
                            pidData:dragPidData
                        })
                    }
                }
                this.dragOtherIds = [];
                __DB__.nodeCheckbox.items = [];
                return;
            }
            
            if(dragPidData.root){
                let leftRoot = this.enterTypeRoot === "left"?true:false;
                if(dragIdData.flip !== leftRoot){
                    fn.call(this,{
                        id:dragId,
                        pid:dragPid,
                        label:dragLabel,
                        nodeType:dragNodeType,
                        pidData:dragPidData
                    });
    
                    if(dragOtherIds.length > 0){
                        for(let el of dragOtherIds){
                            fn.call(this,{
                                id:el,
                                pid:dragPid,
                                label:dragLabel,
                                nodeType:dragNodeType,
                                pidData:dragPidData
                            })
                        }
                    }
                }
                this.dragOtherIds = [];
                __DB__.nodeCheckbox.items = [];
                return;
            }

            function fn(item){
                let dragData  = __tool__.deepCopy(__DB__.get(item.id));

                // 如果是新增节点
                if(!dragData)dragData = fn_drawNewNode(item);
            
                dragData.pid      = item.pid;
                dragData.flip     = item.pidData.flip;
                dragData.type     = "tree";
                
                if(__DB__.get(item.pid).root){
                    dragData.flip = this.enterTypeRoot === "left"?true:false;
                }

                __DB__.del(item.id);
                __DB__.set(item.id,dragData);
            }
        }
        function fn_up(){
                
            dragIdData.pid  = dragPidData.pid;
            dragIdData.flip = dragPidData.flip;
            dragIdData.type = "tree";

            __DB__.set(dragId,dragIdData);
            __DB__.changeIndex(dragId,dragPid,'up');     // 交换位置 
            
            if(dragOtherIds.length > 0){
                for(let el of dragOtherIds){
                    let dragData            = __tool__.deepCopy(__DB__.get(el));
                        dragData.pid        = dragPidData.pid;
                        dragData.flip       = dragPidData.flip;
                        dragData.type       = "tree";

                    __DB__.set(el,dragData);
                    __DB__.changeIndex(el,dragPid,'up');     // 交换位置 
                }

                this.dragOtherIds = [];
                __DB__.nodeCheckbox.items = [];
                
            }
        }
        function fn_down(){
                
            dragIdData.pid  = dragPidData.pid;
            dragIdData.flip = dragPidData.flip;
            dragIdData.type = "tree";
            
            __DB__.set(dragId,dragIdData);
            __DB__.changeIndex(dragId,dragPid,'down');// 交换位置

            if(dragOtherIds.length > 0){
                for(let el of dragOtherIds){
                    let dragData            = __tool__.deepCopy(__DB__.get(el));
                        dragData.pid        = dragPidData.pid;
                        dragData.flip       = dragPidData.flip;
                        dragData.type       = "tree";

                    __DB__.set(el,dragData);
                    __DB__.changeIndex(el,dragPid,'down');     // 交换位置 
                }
                
            }

            this.dragOtherIds = [];
            __DB__.nodeCheckbox.items = [];
        }

        function fn_free(){
            let rootData = __DB__.get('root');
            let root_x = rootData.node.init.poi.x;
            let root_y = rootData.node.init.poi.y;

            let x = root_x - this.rootOffsetX,
                y = root_y - this.rootOffsetY;

            dragIdData.offset           = {
                x : this.rootOffsetX,
                y : this.rootOffsetY,
            }
            // dragIdData.node.init.poi.x  = x;
            // dragIdData.node.init.poi.y  = y;
            dragIdData.pid              = null;
            dragIdData.type             = "free";

            __DB__.set(dragId,dragIdData);

            if(dragOtherIds.length > 0){
                for(let el of dragOtherIds){
                    let dragData            = __tool__.deepCopy(__DB__.get(el));
                        dragData.pid        = null;
                        dragData.type       = "free";

                        let x1 = dragIdData.node.init.poi.x;
                        let y1 = dragIdData.node.init.poi.y;
                        let x2 = dragData.node.init.poi.x;
                        let y2 = dragData.node.init.poi.y;

                        dragData.offset           = {
                            x : this.rootOffsetX + (x1 - x2),
                            y : this.rootOffsetY + (y1 - y2),
                        }

                    __DB__.set(el,dragData);
                }

                this.dragOtherIds = [];
                __DB__.nodeCheckbox.items = [];
            }
        }

        // 拖拽节点是新节点
        function fn_drawNewNode(res){
            let dragIdData = __formate__.nodeDataModel({
                id          : res.id,
                label       : res.label,
                nodeType    : res.nodeType,
                type        : 'tree',
            })

            return dragIdData;

            // data_drawId = __DB__.nodes[drawId];
            // data_drawId.index = __Arr__.nodes.length - 1;
            // index_id = data_drawId.index;
            // $opt.nodeAdd = __tool__.deepCopy(data_drawId);
            // window.dispatchEvent($myEvent.nodeAdd);     // 新增节点
            // window.dispatchEvent($myEvent.undoRedoOpt);// 撤消重做需要的事件回调
            // window.dispatchEvent($myEvent.nodesReset);// 节点重置需要的事件回调
        }
    }

    // 清理重置拖拽时的临时模块
    clear(){
        // this.dragNewNode    = false;//拖拽出新节点
        let nodeIns = document.querySelectorAll('.xmd-node-in');
        let nodeUps = document.querySelectorAll('.xmd-node-up');
        let nodeDowns = document.querySelectorAll('.xmd-node-down');
        nodeIns.forEach(el=>{
            el.setAttribute('class','xmd-node-in');
        });

        nodeUps.forEach(el=>{
            el.setAttribute('class','xmd-node-up');
        });

        nodeDowns.forEach(el=>{
            el.setAttribute('class','xmd-node-down');
        });
        
        this.vBox({show:false});// 清理拖拽时预显示块
        __line__.del({id:"vline"});
    }
}

let drag = new dragClass();
export default drag;